<?php

namespace app\admin\service;

use GatewayWorker\Lib\Gateway;
use think\facade\Log;
use Workerman\Lib\Timer;
use Workerman\Worker;
use think\worker\Application;

/**
 * Worker聊天室
 * @property
 */
class ChatService
{


    /**
     * onWorkerStart 事件回调
     * 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次
     *
     * @access public
     * @param Worker $businessWorker
     * @return void
     */
    public static function onWorkerStart(Worker $businessWorker)
    {
        $app = new Application;
        $app->initialize();
        Timer::add(1, function () {//定时任务，目前心跳自动带有，可以留白

        });
    }

    /**
     * onConnect 事件回调
     * 当客户端连接上gateway进程时(TCP三次握手完毕时)触发
     *
     * @access public
     * @param string $client_id
     * @return void
     */
    public static function onConnect(string $client_id)
    {
//        app('redis')->clear();
//        Gateway::sendToAll("【" . $client_id . "】join the room\n");
    }

    /**
     * onWebSocketConnect 事件回调
     * 当客户端连接上gateway完成websocket握手时触发
     *
     * @param string $client_id 断开连接的客户端client_id
     * @param mixed $data
     * @return void
     */
    public static function onWebSocketConnect(string $client_id, $data)
    {

    }

    /**
     * onMessage 事件回调
     * 当客户端发来数据(Gateway进程收到数据)后触发
     *
     * @access public
     * @param string $client_id
     * @param mixed $data
     * @return void
     */
    public static function onMessage(string $client_id, $data)
    {
        try {
            $data = json_decode($data, true);
            dump($data);
            $type = $data['type'];
            $to_id = $data['to_id'] ?? 0;
            $group = $data['group'] ?? 'admin';
            //组装基本数据
            $msg_data = [
                'from_id' => $data['from_id'],
                'from_username' => $data['from_username'],
                'from_head_img' => $data['from_head_img'],
                'msg' => $data['msg'],
                'type' => $type,
                'to_id' => $to_id,
                'group' => $group
            ];
            $redis_label = ($group . '_chat_' . $client_id) ?? '';
            //区别数据类型
            switch ($type) {
                case 'chat_private'://私聊
                {
                    //发给自己
                    Gateway::sendToCurrentClient(json_encode($msg_data));
                    $to_client_id = Gateway::getClientIdByUid($to_id);
                    //发给对方
                    $uid = $group . '_' . $to_id;
                    Gateway::sendToUid($uid, json_encode($msg_data));
                    //更新自己的私聊数据
                    $client_data = app('redis')->get($redis_label);
                    if(isset($client_data['history_chat'])){
                        $client_data['history_chat'][$to_id] .= self::getTalkHtml($msg_data['from_username']) . $msg_data['msg'];
                    }else{
                        $client_data['history_chat'][$to_id] = self::getTalkHtml($msg_data['from_username']) . $msg_data['msg'];
                    }
                    app('redis')->set($redis_label, $client_data);
                    //更新对方的私聊数据

                    break;
                }
                case 'chat_public'://公共
                {
                    Gateway::sendToAll(json_encode($msg_data));
                    break;
                }
                case 'pong'://心跳回应
                {
                    //TODO 定时清除超市连接
                    break;
                }
                case 'link-in'://绑定会员数据
                {
                    $client_data = [
                        'id' => $data['from_id'],
                        'username' => $data['from_username'],
                        'head_img' => $data['from_head_img'],
                    ];
                    //创建用户数据，用redis缓存
                    app('redis')->set($redis_label, $client_data);
                    //绑定client到系统id并加入群组
                    Gateway::bindUid($client_id, $group . '_' . $data['from_id']);
                    Gateway::joinGroup($client_id, $group);
                    //通知全体会员
                    Gateway::sendToGroup($group, json_encode($msg_data));
                    //更新群组列表到前台
                    self::updateRoomList($group);
                    break;
                }
                case 'link-out'://解绑会员数据
                {
                    //删除缓存
                    app('redis')->has($redis_label) && app('redis')->delete($redis_label);
                    //解除用户绑定，退出群组
                    Gateway::unbindUid($client_id, $group . '_' . $data['from_username']);
                    Gateway::leaveGroup($client_id, $group);
                    //通知全体会员
                    Gateway::sendToGroup($group, json_encode($msg_data));
                    //更新群组列表到前台
                    self::updateRoomList($group);
                    break;
                }
                case 'history_chat'://获取历史聊天数据
                {
                    if ($to_id > 0) {
                        //读取聊天记录
                        $client_data = app('redis')->get($redis_label);
                        $history_chat = ($client_data['history_chat'][$to_id]) ?? '';
                        $msg_data['msg'] = $history_chat;
                        Gateway::sendToClient($client_id, json_encode($msg_data));
                        //TODO 超过一定长度的私聊加入数据库
                    } else {
                        //TODO 群聊暂不加入缓存
                    }
                }
                default:
                    break;
            }
        } catch (\Exception $e) {
            dump($e->getMessage());
            Log::write($e->getMessage(), 'worker-error');
        }


    }

    /**
     * onClose 事件回调 当用户断开连接时触发的方法
     *
     * @param string $client_id 断开连接的客户端client_id
     * @return void
     */
    public static function onClose(string $client_id)
    {

    }

    /**
     * onWorkerStop 事件回调
     * 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。
     *
     * @param Worker $businessWorker
     * @return void
     */
    public static function onWorkerStop(Worker $businessWorker)
    {
        echo "WorkerStop\n";
        Log::write('error', 'worker-info');
    }


    /**
     * @title 更新聊天室用户列表（分组）
     * @param $group
     * @author FashionJune
     */
    private static function updateRoomList($group)
    {
        //更新群组列表到前台
        $client_list = Gateway::getClientIdListByGroup($group);
        $user_list = [];
        foreach ($client_list as $client) {
            $json = app('redis')->get($group . '_chat_' . $client) ?? [];
            $user_list[] = $json;
        }
        $msg_data[$group . '_list'] = $user_list;
        $msg_data['type'] = 'user_list';
        $msg_data['msg'] = 'update';
        Gateway::sendToGroup($group, json_encode($msg_data));
    }

    /**
     * @title 获取文本
     * @author FashionJune
     * @param $username
     */
    private static function getTalkHtml($username){
        return "<br/><span class='chat_username'>【" . $username . "】:</span>";
    }

}
